`timescale 1ns/1ps

module ALU_tb;
    reg [15:0] ACC_in;
    reg [15:0] BR_in;
    reg [7:0] ALU_control;
    reg clk;
    reg rst_n;
    wire [15:0] ALU_out;
    wire [15:0] MR_out;
    wire [8:0] FLAG;

    ALU uut (
        .ACC_in(ACC_in),
        .BR_in(BR_in),
        .ALU_control(ALU_control),
        .clk(clk),
        .rst_n(rst_n),
        .ALU_out(ALU_out),
        .MR_out(MR_out),
        .FLAG(FLAG)
    );

    // 时钟生成
    always #5 clk = ~clk;

    initial begin
        
        clk = 0;
        rst_n = 0;
        ACC_in = 16'h0000;
        BR_in = 16'h0000;
        ALU_control = 8'b0;

        // 释放复位
        #20 rst_n = 1;

        // 测试加法
        #10 ALU_control = 8'b00000001; // add_signal
        ACC_in = 16'h1234;
        BR_in = 16'h5678;
        #10 $display("Add: %h + %h = %h", ACC_in, BR_in, ALU_out);

        // 测试减法
        #10 ALU_control = 8'b00000010; // sub_signal
        ACC_in = 16'h5678;
        BR_in = 16'h1234;
        #10 $display("Sub: %h - %h = %h", ACC_in, BR_in, ALU_out);

        // 测试与操作
        #10 ALU_control = 8'b00000100; // and_signal
        ACC_in = 16'hAAAA;
        BR_in = 16'h5555;
        #10 $display("AND: %h & %h = %h", ACC_in, BR_in, ALU_out);

        // 测试或操作
        #10 ALU_control = 8'b00001000; // or_signal
        ACC_in = 16'hAAAA;
        BR_in = 16'h5555;
        #10 $display("OR: %h | %h = %h", ACC_in, BR_in, ALU_out);

        // 测试乘法
        #10 ALU_control = 8'b01000000; // mul_signal
        ACC_in = 16'h1234;
        BR_in = 16'h5678;
        #10 $display("Mul: %h * %h = %h_%h", ACC_in, BR_in, MR_out, ALU_out);

        // 测试非操作
        #10 ALU_control = 8'b10000000; // not_signal
        ACC_in = 16'h0000;
        #10 $display("NOT: ~%h = %h", ACC_in, ALU_out);

        // 测试标志位
        #10 ALU_control = 8'b00000001; // add_signal
        ACC_in = 16'h8000;
        BR_in = 16'h8000;
        #10 $display("Flags: SF=%b ZF=%b", FLAG[0], FLAG[1]);

        // 测试左移
        #10 ALU_control = 8'b00010000; // lsh_signal
        ACC_in = 16'h1234;
        BR_in = 4; // 移位4位
        #10 $display("LSH: %h << %d = %h", 16'h1234, BR_in, ALU_out);

        // 测试右移
        #10 ALU_control = 8'b00100000; // rsh_signal
        ACC_in = 16'hF000;
        BR_in = 4;
        #10 $display("RSH: %h >> %d = %h", 16'hF000, BR_in, ALU_out);

        // 测试大位数移位
        #10 ALU_control = 8'b00010000; // lsh_signal
        ACC_in = 16'h0001;
        BR_in = 15; // 移位15位
        #10 $display("LSH: %h << 15 = %h", 16'h0001, ALU_out);


        // 结束仿真
        #20 $finish;
    end

endmodule